<template>
  <div
    class="reference"
    :class="attrs.class"
    :style="attrs.style"
    ref="root"
    @click="handleChangeVisible"
  >
    <slot></slot>
  </div>
  <Teleport to="body">
    <div
      ref="popup"
      v-if="visible"
      class="reference-popup fixed z-99 max-h-320px min-w-300px flex flex-col overflow-hidden b-rd-10px bg-#fff p-x-10px p-y-5px shadow"
      :style="poputStyle"
    >
      <div class="body flex-1 overflow-auto">
        <div class="" v-for="item in data" :key="item.value">
          <span class="font-size-14px font-bold">{{ item.label }}</span>
          <div class="p-l-5px">
            <div
              class="flex cursor-pointer flex-justify-between flex-items-center b-rd-5px p-5px font-size-12px color-gray-500 hover:bg-gray-100"
              v-for="op in item.children"
              :key="op.value"
              @click="handleChange(item, op)"
            >
              <span class="font-bold">{{ op.label }}</span>
              <span class="op-60">{{ op.type }}</span>
            </div>
          </div>
        </div>
      </div>
    </div>
  </Teleport>
</template>
<script setup lang="ts">
import { useElementBounding, useWindowSize } from "@vueuse/core";
import { computed, CSSProperties, reactive, ref, useAttrs } from "vue";

interface SelectParams {
  value: string;
  label: string;
  type?: string;
  icon?: string;
  children?: SelectParams[];
}

interface Props {
  trigger?: "auto" | "manual";
}

const attrs = useAttrs() as { class?: string; style?: CSSProperties };
const root = ref<HTMLDivElement>();
const popup = ref<HTMLDivElement>();
const { top, left, height, width } = useElementBounding(root);
const windowSize = useWindowSize();
const { trigger = "auto" } = defineProps<Props>();
const emits = defineEmits(["change", "update"]);
const visible = ref(false);

// 测试数据
const data = reactive<SelectParams[]>([
  {
    label: "开始",
    value: "001",
    children: [
      {
        label: "name",
        value: "name",
      },
      {
        label: "age",
        value: "age",
      },
    ],
  },
  {
    label: "结束",
    value: "002",
    children: [
      {
        label: "name",
        value: "name",
      },
    ],
  },
]);

// 弹出层样式
const poputStyle = computed(() => {
  let y = top.value + height.value + 5;
  let x = left.value;
  // 超出边界
  if (y + 320 > windowSize.height.value) {
    y = windowSize.height.value - 320;
  }
  if (x + 300 > windowSize.width.value) {
    x = windowSize.width.value - 3 - 0;
  }
  return {
    top: y + "px",
    left: x + "px",
    width: width.value + "px",
  };
});

//
const nodeId = defineModel<string>("nodeId", { default: "" });
const name = defineModel<string>("name", { default: "" });

// 选择
const value = ref<string>("");

const handleChangeVisible = () => {
  if (trigger == "manual") {
    return;
  }
  visible.value = !visible.value;
};
const handleChange = (parent: SelectParams, child: SelectParams) => {
  nodeId.value = parent.value;
  name.value = child.value;

  emits("change", {
    nodeId: parent.value,
    name: child.value,
    type: child.type,
  });
  handleChangeVisible();
};

defineExpose({
  show() {
    visible.value = true;
  },
  close() {
    visible.value = false;
  },
});
</script>
